package com.dhh.rxwebsocket;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.dhh.rxlifecycle2.RxLifecycle;
import com.dhh.rxwebsocket.util.ByteUtils;
import com.dhh.websocket.Config;
import com.dhh.websocket.RxWebSocket;
import com.dhh.websocket.WebSocketInfo;
import com.dhh.websocket.WebSocketSubscriber;
import com.dhh.websocket.WebSocketSubscriber2;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.zip.CRC32;

import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okio.ByteString;

public class MainActivity extends AppCompatActivity {
    private WebSocket mWebSocket;
    private EditText editText;
    private Button send;
    private Button centect;
    private Disposable mDisposable;
    private TextView textview;
    private String url;
    //    private String loginPath = " ws://localhost:47015/";
    private String loginPath = "ws://10.7.5.88:8089/status";
    private MockWebServer mockWebServer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();

        //init config
        Config config = new Config.Builder()
                .setShowLog(true)           //show  log
                .setClient(new OkHttpClient.Builder()
                        .pingInterval(1, TimeUnit.SECONDS)//设置心跳间隔，这个是3秒检测一次
                        .build())   //if you want to set your okhttpClient
//                .setShowLog(true, "your logTag")
//                .setReconnectInterval(2, TimeUnit.SECONDS)  //set reconnect interval
//                .setSSLSocketFactory(yourSSlSocketFactory, yourX509TrustManager) // wss support
                .build();
        RxWebSocket.setConfig(config);
        // use WebSocketSubscriber 生命周期管理
//        RxWebSocket.get(loginPath)
//                //RxLifecycle : https://github.com/dhhAndroid/RxLifecycle
//                .compose(RxLifecycle.with(this).<WebSocketInfo>bindToLifecycle())
//                .subscribe(new WebSocketSubscriber() {
//                    @Override
//                    public void onOpen(@NonNull WebSocket webSocket) {
//                        Log.d("MainActivity", "onOpen1:");
//                    }
//
//                    @Override
//                    public void onMessage(@NonNull String text) {
//                        Log.d("MainActivity", "text  " + text);
//                    }
//
//                    @Override
//                    public void onMessage(@NonNull ByteString bytes) {
//                        Log.d("MainActivity", "ByteString  ");
//                    }
//
//                    @Override
//                    protected void onReconnect() {
//                        Log.d("MainActivity", "重连");
//                    }
//
//                    @Override
//                    protected void onClose() {
//
//                    }
//
//                    @Override
//                    public void onError(Throwable e) {
//
//                    }
//                });

//        RxWebSocket.get(loginPath)
//                .subscribe(new WebSocketSubscriber() {
//                    @Override
//                    protected void onMessage(String text) {
//                        Log.d("MainActivity", "text  "+text);
//                    }
//
//                    @Override
//                    protected void onReconnect() {
//                        Log.d("MainActivity", "重连");
//                    }
//                });

        /**
         *
         *如果你想将String类型的text解析成具体的实体类，比如{@link List<String>},
         * 请使用 {@link  WebSocketSubscriber2}，仅需要将泛型传入即可
         */
//        RxWebSocket.get(loginPath)
//                .compose(RxLifecycle.with(this).<WebSocketInfo>bindToLifecycle())
//                .subscribe(new WebSocketSubscriber2<List<String>>() {
//                    @Override
//                    protected void onMessage(List<String> strings) {
//
//                    }
//                });

        //注销
//        Disposable disposable = RxWebSocket.get("ws://sdfs").subscribe();
//        if (disposable != null && !disposable.isDisposed()) {
//            disposable.dispose();
//        }

        initDemo();
    }

    @Override
    protected void onResume() {
        super.onResume();
//       RxWebSocket.get("")
//                //RxLifecycle : https://github.com/dhhAndroid/RxLifecycle
//                .compose(RxLifecycle.with(this).<WebSocketInfo>bindToLifecycle())
//                .subscribe(new WebSocketSubscriber() {
//                    @Override
//                    public void onOpen(@NonNull WebSocket webSocket) {
//                        Log.d("MainActivity", "onOpen1:");
//                    }
//
//                    @Override
//                    public void onMessage(@NonNull String text) {
//                        Log.d("MainActivity", "返回数据:" + text);
//                    }
//
//                    @Override
//                    public void onMessage(@NonNull ByteString byteString) {
//                        Log.d("MainActivity", "ByteString  ");
//                    }
//
//                    @Override
//                    protected void onReconnect() {
//                        Log.d("MainActivity", "重连:");
//                    }
//
//                    @Override
//                    protected void onClose() {
//                        Log.d("MainActivity", "onClose:");
//                    }
//                });

    }

    private void initDemo() {
        Schedulers.io().createWorker().schedule(new Runnable() {
            @Override
            public void run() {
                mockWebServer = new MockWebServer();
                url = "ws://" + mockWebServer.getHostName() + ":" + mockWebServer.getPort() + "/";
                Log.d("MainActivity", "url:  " + url);
                //模拟后台
                initServerWebsocket();
            }
        });
//        connect();
        setListener();
    }

    private void initServerWebsocket() {

        mockWebServer.enqueue(new MockResponse().withWebSocketUpgrade(new WebSocketListener() {
            @Override
            public void onOpen(WebSocket webSocket, Response response) {
                webSocket.send("hello,I am from server websocket,successful connection!");
            }

//            @Override
//            public void onMessage(WebSocket webSocket, String text) {
//                Log.d("MainActivity", "收到客户端消息:" + text);
//                webSocket.send("Server response:" + text);
//            }

            @Override
            public void onMessage(WebSocket webSocket, ByteString bytes) {
                super.onMessage(webSocket, bytes);
                String s = bytes.toString();
                byte[] bytesList = bytes.toByteArray();
                String result = new String(bytesList, 4, bytesList.length - 8);

                Log.d("MainActivity", "收到客户端消息:" + s);
                webSocket.send("Server response:  " + result);
            }


            @Override
            public void onClosed(WebSocket webSocket, int code, String reason) {

            }

            @Override
            public void onFailure(WebSocket webSocket, Throwable t, Response response) {
            }
        }));
    }

    private void setListener() {
        //send message
        send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String msg = editText.getText().toString().trim();
                if (!TextUtils.isEmpty(msg)) {
                    send(msg);
                }

            }
        });
        centect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                connect();

            }
        });

    }

    private void connect() {
//        Log.d("MainActivity", " Disposable == null?  " + (mDisposable == null));
//        if (mDisposable != null) return;
//        //注意取消订阅,有多种方式,比如 rxlifecycle
//        mDisposable = RxWebSocket.get(url)
//                // RxLifeCycle: https://github.com/dhhAndroid/RxLifecycle
//                .compose(RxLifecycle.with(this).<WebSocketInfo>bindOnDestroy())
//                .subscribe(new Consumer<WebSocketInfo>() {
//                    @Override
//                    public void accept(WebSocketInfo webSocketInfo) throws Exception {
//                        mWebSocket = webSocketInfo.getWebSocket();
//                        if (webSocketInfo.isOnOpen()) {
//                            Log.d("MainActivity", " on WebSocket open");
//                        } else {
//
//                            String string = webSocketInfo.getString();
//                            if (string != null) {
//                                Log.d("MainActivity", "connect str  " + string);
//                                textview.setText(Html.fromHtml(string));
//
//                            }
//
//                            ByteString byteString = webSocketInfo.getByteString();
//                            if (byteString != null) {
//                                Log.d("MainActivity", "webSocketInfo.getByteString():" + byteString);
//
//                            }
//                        }
//                    }
//                });


        RxWebSocket.get(url)
                //RxLifecycle : https://github.com/dhhAndroid/RxLifecycle
                .compose(RxLifecycle.with(this).<WebSocketInfo>bindToLifecycle())
                .subscribe(new WebSocketSubscriber() {
                    @Override
                    public void onOpen(@NonNull WebSocket webSocket) {
                        Log.d("MainActivity", "onOpen1:");
                        mWebSocket = webSocket;
                    }

                    @Override
                    public void onMessage(@NonNull String text) {
                        Log.d("MainActivity", "返回数据:" + text);
                        textview.setText(Html.fromHtml(text));
                    }

                    @Override
                    public void onMessage(@NonNull ByteString byteString) {
                        Log.d("MainActivity", "ByteString  ");
                    }

                    @Override
                    protected void onReconnect() {
                        Log.d("MainActivity", "重连:");
                    }

                    @Override
                    protected void onClose() {
                        Log.d("MainActivity", "onClose:");
                    }
                });
    }

    public void send(String msg) {
        //引用直接发
//        mWebSocket.send("hello");
//        //url 对应的WebSocket 必须打开,否则报错
//        RxWebSocket.send(url, "hello");
//        RxWebSocket.send(url, ByteString.EMPTY);
//        //异步发送,若WebSocket已经打开,直接发送,若没有打开,打开一个WebSocket发送完数据,直接关闭.
//        RxWebSocket.asyncSend(url, "hello");
//        RxWebSocket.asyncSend(url, ByteString.EMPTY);

        ByteString byteString = ByteString.of(pack(msg), 0, pack(msg).length);
        if (mWebSocket != null) {
            mWebSocket.send(byteString);
            Log.d("MainActivity", "WebSocket不为空");
        } else {
            RxWebSocket.send(url, byteString);
            Log.d("MainActivity", "WebSocket为空");
        }
    }

    /**
     * 封装报文数据
     */
    private static byte[] pack(String jsonData) {
        //json对象格式
        byte[] senddata = jsonData.getBytes();

        // 得到报文总长度
        int len = senddata.length;
        byte[] byLens = ByteUtils.intToBytes(len);

        // 输出报文长度
        short totalSize = (short) (2 + 2 + 2 + 2 + len);
        byte[] lenByte = ByteUtils.shortToByte(totalSize);

        // 得到data验证码
        CRC32 sCrc32 = new CRC32();
        sCrc32.update(senddata);
        long valueL = sCrc32.getValue();
        byte[] crc32 = ByteUtils.long2Bytes(valueL);
//            for (byte b : crc32) {
//                int head1 = Integer.parseInt(ByteUtils.byteToHex(b), 16);
//                Log.d(TAG, "csc32校验码   " + head1);
//            }

        // 需要传输的字段
        byte[] bytes = new byte[2 + 2 + 2 + 2 + len];
        int index = 0;
        bytes[index++] = (byte) 0xff;// 前导字节
        bytes[index++] = (byte) 0xff;// 前导字节

        //数据长度 len[2]: 长度位宽度2字节，使用uint16最大数据长度65536个字节即data[65535]为最大长度，len[0]uint16高8位，len[1]uint16低8位
        bytes[index++] = byLens[0];
        bytes[index++] = byLens[byLens.length - 1];

        // 数据包中的真实数据结构的字节化数据
        for (byte aSenddata : senddata) {
            bytes[index++] = aSenddata;
        }

        //校验码 crc[2]: data[n]的crc32校验字节宽度2个字节，crc[0]crc32高1字节，crc[1]crc32高2字节
//            for (byte sCrc32 : crc32) {
//                bytes[index++] = sCrc32;
//            }
        bytes[index++] = crc32[4];
        bytes[index++] = crc32[5];

        //后缀字节
        bytes[index++] = (byte) 0xff;// 后缀字节
        bytes[index] = (byte) 0xfe;// 后缀字节
//        for (int i = 0; i < bytes.length; i++) {
//            int head1 = Integer.parseInt(ByteUtils.byteToHex(bytes[i]), 16);
//            Log.d("MainActivity", "客户端数据发送前   " + head1);
//        }

        return bytes;
    }

    private void initView() {
        editText = (EditText) findViewById(R.id.editText);
        send = (Button) findViewById(R.id.send);
        centect = (Button) findViewById(R.id.centect);
        textview = (TextView) findViewById(R.id.textview);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
//        if (mDisposable != null) {
//            mDisposable.dispose();
//        }
    }
}
